package com.cms.security;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import com.cms.entity.Action;
import com.cms.entity.Admin;
import com.cms.entity.Role;
import com.cms.service.AdminService;

/**
 * @see 登录验证
 * @author zhangp
 */
@Component("loginAuditHandler")
public class LoginAuditHandler implements AuthenticationSuccessHandler,
		AuthenticationFailureHandler {

	private static final Logger LOGGER = LoggerFactory
			.getLogger(LoginAuditHandler.class);
	@Autowired
	private AdminService adminService;

	public void onAuthenticationFailure(HttpServletRequest request,
			HttpServletResponse response, AuthenticationException exception)
			throws IOException, ServletException {
		response.sendRedirect(request.getContextPath() + "/login?error=01");
		@SuppressWarnings("deprecation")
		String userName = exception.getAuthentication().getPrincipal()
				.toString();
		try {
			Admin user = adminService.loadUser(userName);
			user.setLoginFailureCount(user.getLoginFailureCount() + 1);
			if (user.getLoginFailureCount() >= 5) {
				user.setStatus(1); // 冻结用户
			}
			adminService.updateUser(user);
		} catch (Exception e) {
			LOGGER.info("用户名:" + userName + ",登录失败");
		}
	}

	public void onAuthenticationSuccess(HttpServletRequest request,
			HttpServletResponse response, Authentication authentication)
			throws IOException, ServletException {
		HashMap<String, String> authMap = new HashMap<String, String>();
		HttpSession session = request.getSession();
		Admin user = (Admin) authentication.getPrincipal();
		if (user.getStatus() != null && user.getStatus() != 0) {
			response.sendRedirect(request.getContextPath() + "/login?error=03");
			return;
		} else {
			session.setAttribute("username", user.getUsername());
			String userHost = request.getRemoteHost();

			String sessionId = request.getSession().getId();

			UserSession userSession = new UserSession();

			userSession.setUsername(user.getUsername());

			userSession.setSessid(sessionId);

			userSession.setAddr(userHost);

			userSession.setModifyPwd(isToModifyPassWord(user.getUsername()));

			session.setAttribute("userSession", userSession);

			// 记录登录信息
			adminService.recordLogin(user.getUsername(),
					request.getRemoteAddr());
			// 用户权限集合写入session供权限验证标签使用
			if (user != null) {
				Set<Role> set = (Set<Role>) user.getAuthorities();
				Iterator<Role> itRole = set.iterator();
				while (itRole.hasNext()) {
					Role role = itRole.next();
					Iterator<Action> actionIt = role.getActions().iterator();
					while (actionIt.hasNext()) {
						authMap.put(actionIt.next().getUrl(),
								role.getAuthority());
					}
				}
				session.setAttribute("auth", authMap);
			}
			response.sendRedirect(request.getContextPath());
		}

	}

	/**
	 * 是否需要跳转到修改密码页面 （口令是否过期，第一次登录要求修改密码）
	 * 
	 * @return
	 */
	private boolean isToModifyPassWord(String userName) {
		Admin user = adminService.loadUser(userName);
		Date date = user.getLastModifyPsdDate();
		if (date == null) {
			return true;
		}
		if (new Date().getTime() - date.getTime() > 30 * 24 * 60 * 60 * 1000L) {
			return true;
		}
		return false;
	}

}
